package cloud.alibaba.sentinel.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @auther xfanonymous
 * @create 2024-01-03 17:25
 *
 * Sentinel P2
 * 验证 @SentinelResource 注解功能
 * 1. 默认对URL添加流控，触发熔断后，返回默认限流提示Blocked by Sentinel (flow limiting)
 * 2. 通过注解@SentinelResource()自定义资源名和限流提示，value指定资源名，和控制台添加流控规则时的资源名一致，blockHandler指定超过流控规则后，执行的自定义限流提示。
 * 3. 通过注解@SentinelResource()自定义降级方法，fallback指定程序异常后，要执行的降级方法
 */
@RestController
@Slf4j
public class RateLimitController
{
    // 默认对URL添加流控，触发熔断后，返回默认限流提示Blocked by Sentinel (flow limiting)
    @GetMapping("/rateLimit/byUrl")
    public String byUrl() {
        return "按rest地址限流测试OK";
    }

    /** 通过注解@SentinelResource()自定义资源名和限流提示
     * 1. value指定资源名，和控制台添加流控时的资源名一致
     * 2. blockHandler指定超过流控规则后，执行的自定义限流提示
     */
    @GetMapping("/rateLimit/byResource")
    @SentinelResource(value = "byResourceSentinelResource", blockHandler = "handlerBlockHandler")
    public String byResource() {
        return "按照资源名称SentinelResource限流测试OK，O(∩_∩)O";
    }

    public String handlerBlockHandler(BlockException blockException) {
        return "服务不可用触发@SentinelResource启动blockHandler，/(ㄒoㄒ)/~~";
    }


    /** 通过注解@SentinelResource(fallback="") 自定义降级方法
     * fallback指定程序异常后，要执行的降级方法
     */
    @GetMapping("/rateLimit/doAction/{p1}")
    @SentinelResource(value = "doActionSentinelResource",
            blockHandler = "doActionBlockHandler", fallback = "doActionFallback")
    public String doAction(@PathVariable("p1") Integer p1) {
        if (p1 == 0){
            throw new RuntimeException("p1等于零直接异常");
        }
        return "doAction";
    }

    public String doActionBlockHandler(@PathVariable("p1") Integer p1,BlockException e){
        log.error("sentinel配置自定义限流了:{}", e);
        return "sentinel配置自定义限流了";
    }

    public String doActionFallback(@PathVariable("p1") Integer p1,Throwable e){
        log.error("程序逻辑异常了:{}", e);
        return "程序逻辑异常了"+"\t"+e.getMessage();
    }


    /** Sentinel热点规则
     * 热点参数限流，分别对p1、p2参数限流
     * 只有带有?p1的高流量访问会触发限流
     */
    @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey", blockHandler = "dealHandler_testHotKey")
    public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                             @RequestParam(value = "p2", required = false) String p2) {
        return "------testHotKey";
    }

    public String dealHandler_testHotKey(String p1,String p2,BlockException exception) {
        return "-----dealHandler_testHotKey";
    }
}
